package org.vectrics.common.db;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.vectrics.SystemException;
import org.vectrics.hibernate.HibernateUtil;
import org.vectrics.provider.CoreServiceLocator;

/**
 * @author mmoore
 */
public class SurrogateKeyService {
	private transient final Logger log = Logger.getLogger(SurrogateKeyService.class);
	
	public SurrogateKeyService() {
	}
	
	public synchronized Long getKey(String code) {
		/*
		SurrogateKeyRunnable runnable = new SurrogateKeyRunnable(code);
		Thread newKeyThread = new Thread(runnable);
		newKeyThread.start();
		try {
			while (newKeyThread.isAlive()) { 
				Thread.sleep(50);
			}
		} catch (Exception ex) {
			throw new SystemException("Exception using thread to acquire surrogate key", ex);
		}*/
		
        HibernateUtil hibernate = (HibernateUtil)CoreServiceLocator.findServiceBean("hibernate.util");
        Session session = hibernate.createNewSession();
		Transaction trx = session.beginTransaction();
		Long id = this.runWithHibernateObjects(session, code);
    	trx.commit();
		session.flush();
    	session.close();

        hibernate = (HibernateUtil)CoreServiceLocator.findServiceBean("hibernate.util");
        session = hibernate.createNewSession();
		trx = session.beginTransaction();
		SurrogateKey surrogateKey = (SurrogateKey)session.load(SurrogateKey.class, code);
		Long checkId = surrogateKey.getId();
    	trx.commit();
		session.flush();
    	session.close();
    	
    	if (checkId.longValue() <= id.longValue()) {
    		throw new SystemException("New Surrogate Key was not persisted properly, readback id not greater than prev id.   ID=" + id 
				+  "  Check ID = " + checkId);
    	}
    	
		return(id);
	}
	
	private synchronized Long runWithHibernateObjects(Session session, String surrogateKeyCode) {
		log.debug("Surrogate key runnable.run()");
		SurrogateKey surrogateKey = (SurrogateKey)session.load(SurrogateKey.class, surrogateKeyCode);
		Long id = surrogateKey.getId();
		
		if (log.isDebugEnabled())
			log.debug("Surrogate key, code = " + surrogateKeyCode + " Current id = " + id);
		
		if (id.compareTo(surrogateKey.getStartId()) < 0) {
			if (log.isDebugEnabled())
				log.debug("Surrogate key less than surrogate's start id, " +
						"setting to start id - code = " + surrogateKeyCode);
			id = surrogateKey.getStartId();
		}
		
		surrogateKey.setId(new Long(id.longValue() + 1));
		if (surrogateKey.getId().longValue() != id.longValue() + 1)
			throw new SystemException("Logic error, saving incremented id, not greater than previous.  ID = " + id 
					+  "  Check ID = " + surrogateKey.getId());
		session.update(surrogateKey);
		
		

		return(id);
	}
	
	
/*	
	public synchronized Long getKey_Old(String code) {
		Long id = null;
		testCount++;
		if (testCount > 1)
			throw new SystemException("Test count greater than 1 - code = " + code);
		hibernate.getSessionFactory().evict(SurrogateKey.class);
        HibernateUtil hibernate = (HibernateUtil)CoreServiceLocator.findServiceBean("hibernate.util");
        Session session = hibernate.createNewSession();
        //session.setCacheMode(CacheMode.PUT);
        session.clear();
        Transaction transaction = session.beginTransaction();
		SurrogateKey surrogateKey = (SurrogateKey)session.load(SurrogateKey.class, code);
		id = surrogateKey.getId();
		
		if (log.isDebugEnabled())
			log.debug("Surrogate key, code = " + code + " Current id = " + id);
		
		if (id.compareTo(surrogateKey.getStartId()) < 0) {
			if (log.isDebugEnabled())
				log.debug("Surrogate key less than surrogate's start id, setting to start id - code = " + code);
			id = surrogateKey.getStartId();
		}
		
		surrogateKey.setId(new Long(id.longValue() + 1));
		if (surrogateKey.getId().longValue() <= id.longValue())
			throw new SystemException("Logic error, saving incremented id, not greater than previous");
		session.update(surrogateKey);
		transaction.commit();
		session.evict(surrogateKey);

		hibernate.getSessionFactory().evict(SurrogateKey.class);
		surrogateKey = (SurrogateKey)session.load(SurrogateKey.class, code);
		if (surrogateKey.getId().longValue() != id.longValue())
			throw new SystemException("Exception getting surrogate key, readback failed");
		session.evict(surrogateKey);
		hibernate.getSessionFactory().evict(SurrogateKey.class);
		session.close();
		testCount--;
		return(id);
	}
	*/
}
